/**
 *
 */
package com.gz.droolsrule.util;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.util.JSONPObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author light
 */
@Slf4j
public class JsonUtil {
    private static ObjectMapper mapper = createMapper();
    public static ObjectMapper getMapper() {
        return mapper;
    }
    public static ObjectMapper createMapper() {
        ObjectMapper result = new ObjectMapper();
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        result.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        result.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        result.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        // 设置输出时包含属性的风格
        result.setSerializationInclusion(Include.NON_EMPTY);
        return result;
    }

    public static Map readValue(String json) {
        try {
            return mapper.readValue(json, Map.class);
        } catch (IOException e) {
            log.warn("read json string error", e);
            return null;
        }
    }

    public static String readValueString(String json, String key) {
        Map map = readValue(json);
        if (map == null) {
            return null;
        }
        return map.get(key).toString();
    }

    public static <E> String beanToJson(E object) {
        try {
            String s = mapper.writeValueAsString(object);
            if ("null".equals(s)){
                s = null;
            }
            return s;
        } catch (IOException e) {
            log.warn("write to json string error:" + object, e);
            return null;
        }
    }

    public static <E> E jsonToBean(InputStream input, Class<E> clazz) {
        if (input == null) {
            return null;
        }
        try {
            return mapper.readValue(input, clazz);
        } catch (IOException e) {
            log.warn("parse json error", e);
            return null;
        }
    }

    public static <E> E jsonToBean(String str, Class<E> clazz) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        try {
            return mapper.readValue(str, clazz);
        } catch (IOException e) {
            log.warn("parse json string error:" + str, e);
            return null;
        }
    }

    public static <E> E jsonToBean(String str, TypeReference<E> typeReference) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        try {
            return mapper.readValue(str, typeReference);
        } catch (IOException e) {
            log.warn("parse json string error:" + str, e);
            return null;
        }
    }

    public static <E> List<E> jsonToList(String str, Class<?> elementClasses) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        try {
            JavaType javaType = getCollectionType(ArrayList.class, elementClasses);
            return (List<E>) mapper.readValue(str, javaType);
        } catch (IOException e) {
            log.warn("parse json string error:" + str, e);
            return null;
        }
    }
    
    public static JsonNode parseNode(String text) {
        try {
            return mapper.readTree(text);
        } catch (IOException e) {
            log.warn("parse json error:" + text, e);
            return null;
        }
    }
    
    /**
     * 获取泛型的Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  元素类
     * @return JavaType Java类型
     */
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

    /**
     * 输出JSONP格式数据.
     */
    public static String beanToJsonP(String functionName, Object object) {
        return beanToJson(new JSONPObject(functionName, object));
    }


}
